/*
 ******************************
 * Object Oriented Programming in C
 *
 * Author: Laurent Deniau, Laurent.Deniau@cern.ch
 *
 * For more information, please see the paper:
 * http://home.cern.ch/ldeniau/html/oopc/oopc.html
 *
 ******************************
 */

#include <stdio.h>
#include <math.h>
#include <oodebug.h>
#include <exception.h>

/* can also be #defined */
enum { no_exception, zero_divide, domain_error } exceptions;

void
free_char(char *p)
{
  printf("protected pointer %p automatically freed\n", p);
  free(p);
}

double
div_(DEBUG_PROTO double a, double b)
{
  DEBUG_DISPCALL(stderr, "func call trace");
  if (b == 0.0) throw(zero_divide);
  return a/b;
}

double
div2_(DEBUG_PROTO double a, double b)
{
  double c;
  char *ptr  = malloc(10*sizeof(char));
  protectPtr(ptr, free_char);
  DEBUG_DISPCALL(stderr, "func call trace");
  printf("%p protected\n", ptr);

  c = div_(DEBUG_ARGS a,b);

  printf("%p unprotected\n", ptr);
  unprotectPtr(ptr);
  unprotectPtr(ptr); /* does nothing */
  printf("%p freed\n", ptr);
  free(ptr);

  return c;
}

int
main(int argc, char *argv[])
{
  double a, b;

  if (argc!=3) return EXIT_FAILURE;
  a = atof(argv[1]);
  b = atof(argv[2]);

  try {
    printf("div2(%g/%g) = %g\n", a, b, div2_(DEBUG_ARGS a,b));
  }
  catch(zero_divide) {
    printf("zero division\n");
  }
  catch_any {
    printf("unknow exception no %d\n", exception);
  }
  endtry;

  DEBUG_DISPMEM(stderr);

  return EXIT_SUCCESS;
}
